package gen

import (
	"bufio"
	"github.com/worryry/8-pigeons/pkg/database/mysql"
	"gorm.io/gen"
	"io"
	"io/ioutil"
	"os"
	"path/filepath"
	"strings"
)

const GenModelPath = "./internal/models"

func Start() {
	// 指定生成代码的具体相对目录(相对当前文件)，默认为：./query
	// 默认生成需要使用WithContext之后才可以查询的代码，但可以通过设置gen.WithoutContext禁用该模式
	g := gen.NewGenerator(gen.Config{
		// 默认会在 OutPath 目录生成CRUD代码，并且同目录下生成 model 包
		// 所以OutPath最终package不能设置为model，在有数据库表同步的情况下会产生冲突
		// 若一定要使用可以通过ModelPkgPath单独指定model package的名称
		OutPath: GenModelPath + "/query",
		/* ModelPkgPath: "dal/model"*/

		// gen.WithoutContext：禁用WithContext模式
		// gen.WithDefaultQuery：生成一个全局Query对象Q
		// gen.WithQueryInterface：生成Query接口
		Mode: gen.WithDefaultQuery | gen.WithQueryInterface | gen.WithoutContext,
	})

	// 通常复用项目中已有的SQL连接配置db(*gorm.DB)
	// 非必需，但如果需要复用连接时的gorm.Config或需要连接数据库同步表信息则必须设置
	g.UseDB(mysql.DB)

	// 从连接的数据库为所有表生成Model结构体和CRUD代码
	// 也可以手动指定需要生成代码的数据表
	g.ApplyBasic(g.GenerateAllTable()...)

	//tables, err := mysql.DB.Migrator().GetTables()
	//if err != nil {
	//	panic(fmt.Errorf("get all tables fail: %w", err))
	//}
	//tableModels := make([]interface{}, len(tables))
	//
	////获取当前已经生成的model
	//exists, _ := GetExistTables(GenModelPath + "/model")
	//i := 0
	//for _, table := range tables {
	//	if !array.InArray(table, exists) {
	//		tableModels[i] = g.GenerateModel(table)
	//		i++
	//	}
	//}
	//g.ApplyBasic(tableModels...)

	// 执行并生成代码
	g.Execute()

	//query.SetDefault(mysql.DB)
}

// 读取已经生成model的表
func GetExistTables(path string) (table []string, err error) {
	fis, err := ioutil.ReadDir(filepath.Clean(filepath.ToSlash(path)))
	if err != nil {
		return nil, err
	}
	for _, f := range fis {
		_path := filepath.Join(path, f.Name())
		if f.IsDir() {
			tb, _ := GetExistTables(_path)
			table = append(table, tb...)
			continue
		}
		//读取文件中的表名
		open, err := os.Open(_path)
		if err != nil {
			continue
		}
		r := bufio.NewReader(open)
		for {
			bytes, _, err := r.ReadLine()
			if err == io.EOF {
				break
			}
			if strings.Contains(string(bytes), "const TableName") {
				//解析表名
				arr := strings.Split(string(bytes), " = ")
				table = append(table, strings.Trim(arr[1], "\""))
				break
			}
		}
		_ = open.Close()
	}
	return table, err
}
